﻿using System;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;
using FrameWork.Log;
using System.ComponentModel;
using FrameWork.Setting;

namespace MyServer.Common
{
    /// <summary>
    /// 数据侦听器基类
    /// </summary>
    [SettingParentDefine]
    public abstract class DataListenerBase : LogableClassBase
    {

        #region========私有变量========

        /// <summary>
        /// 线程锁对象
        /// </summary>
        private object ListenLockObj = new object();
        private object ListenLockFullObj = new object();

        /// <summary>
        /// 关闭标识
        /// </summary>
        private bool IsStop = false;

        #endregion

        #region==========属性==========

        /// <summary>
        /// 表示与数据侦听器关联的数据收发中心
        /// </summary>
        [DisplayName("数据收发中心")]
        [Description("表示与数据侦听器关联的数据收发中心")]
        public DataCenterBase Center { get; protected set; }

        /// <summary>
        /// 表示数据侦听器的主侦听工作
        /// </summary>
        protected Task ListenMainTask { get; set; }

        /// <summary>
        /// 表示侦听器目前侦听的客户端列表
        /// </summary>
        protected ArrayList ListenQueue { get; set; }

        /// <summary>
        /// 获取或设置侦听器侦听的频率
        /// </summary>
        [SettingItemDefine(SettingValueType.Int32,10)]
        [Browsable(true)]
        [Category("常规")]
        [DisplayName("侦听频率")]
        [Description("表示数据侦听线程在没有数据录入时睡眠的时间")]
        public int ListenRate { get; set; }

        /// <summary>
        /// 获取或设置侦听器的超时时间
        /// </summary>
        [SettingItemDefine(SettingValueType.Int32,10000)]
        [Browsable(true)]
        [Category("常规")]
        [DisplayName("超时时间")]
        [Description("表示数据侦听器的超时时间")]
        public int ListenTimeOutValue { get; set; }

        #endregion

        #region========公有委托========

        /// <summary>
        /// 为数据可用事件提供委托
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public delegate void DataAvailableEventHandler(object sender, DataListenerEventArgs e);

        /// <summary>
        /// 为监听超时事件提供委托
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public delegate void ListenTimeOutEventHandler(object sender, DataListenerEventArgs e);

        #endregion

        #region==========事件==========

        /// <summary>
        /// 当数据可用时触发的事件
        /// </summary>
        public event DataAvailableEventHandler DataAvailable;

        /// <summary>
        /// 当数据监听超时时触发的事件
        /// </summary>
        public event ListenTimeOutEventHandler ListenTimeOut;

        #endregion

        #region========私有函数========
        /// <summary>
        /// 打包连接
        /// </summary>
        private void PackConnect(ListenItem obj, int datal)
        {
            DataPackageCollection col = new DataPackageCollection("", PackageCollectionType.ForRecive);
            col.Tag = obj.Connect;
            DataListenerEventArgs e = new DataListenerEventArgs(col, datal, obj.Connect);

            if (DataAvailable != null)
                DataAvailable(this, e);

            if (e.IsCancel)
            {
                ClearData(obj.Connect);
            }
            else
            {
                this.ListenQueue.Remove(obj);
            }
        }
        /// <summary>
        /// 开始侦听
        /// </summary>
        protected void DoListen()
        {
            lock (ListenLockFullObj)
            {
                PrintLog(LogType.Info, "监听主工作线程已启动！");
                while (IsStop == false)
                {
                    if (ListenQueue.Count == 0)
                    {
                        System.Threading.Thread.Sleep(ListenRate);
                        continue;
                    }
                    lock (ListenLockObj)
                    {
                        bool IsDataRecived = false;
                        foreach (ListenItem obj in ListenQueue.ToArray())
                        {
                            int datal = CheckDataAvilable(obj.Connect);
                            if (datal > 0)
                            {
                                IsDataRecived = true;
                                obj.LastReciveDataTime = Environment.TickCount;
                                PackConnect(obj, datal);
                            }
                            else
                            {
                                if ((Environment.TickCount-obj.LastReciveDataTime) >= ListenTimeOutValue && ListenTimeOutValue != -1)
                                {
                                    DataListenerEventArgs e1 = new DataListenerEventArgs(null, datal, obj.Connect);
                                    if (ListenTimeOut != null)
                                    {
                                        PrintLog(LogType.Waring, "连接已超时，正在处理...");
                                        ListenTimeOut(this, e1);
                                    }
                                    if (!e1.IsCancel)
                                    {
                                        PrintLog(LogType.Info, "正在移除已超时的连接....", obj);
                                        ListenQueue.Remove(obj);
                                    }
                                }
                            }
                        }
                        if(IsDataRecived)
                        {
                            continue;
                        }
                        else
                        {
                            System.Threading.Thread.Sleep(ListenRate);
                        }
                    }
                }
                PrintLog(LogType.Info, "监听主工作线程已结束！");
            }
        }

        #endregion

        #region========抽象函数========

        /// <summary>
        /// 检查指定的客户端有无数据
        /// </summary>
        /// <param name="Client">要检查的客户端</param>
        /// <returns>当前客户端的挂起的数据量</returns>
        public abstract int CheckDataAvilable(object Client);

        /// <summary>
        /// 清除目标客户端的请求数据
        /// </summary>
        /// <param name="Client"></param>
        /// <returns></returns>
        public abstract bool ClearData(object Client);

        #endregion

        #region========构造函数========

        /// <summary>
        /// 通过指定的数据中心创建数据侦听器实例
        /// </summary>
        /// <param name="Center">绑定的数据中心</param>
        public DataListenerBase(DataCenterBase Center)
        {
            this.Center = Center;
            this.ListenMainTask = new Task(DoListen);
            this.ListenQueue = System.Collections.ArrayList.Synchronized(new ArrayList());
            this.ListenRate = 10;
            this.ListenTimeOutValue = 10000;
        }

        #endregion

        #region========公有函数========

        /// <summary>
        /// 开启数据侦听器
        /// </summary>
        /// <returns></returns>
        public bool Start()
        {
            PrintLog(LogType.Info, "正在启动侦听器...");
            if (this.ListenMainTask.Status == TaskStatus.RanToCompletion)
            {
                PrintLog(LogType.Info, "正在重构主工作线程...");
                this.ListenMainTask = new Task(DoListen);
            }
            PrintLog(LogType.Info, "正在启动主工作线程...");
            this.ListenMainTask.Start();
            PrintLog(LogType.Info, "侦听器启动成功！");
            return true;
        }

        /// <summary>
        /// 停止数据侦听器
        /// </summary>
        /// <returns></returns>
        public bool Stop()
        {
            PrintLog(LogType.Info, "正在停止侦听器...");
            IsStop = true;
            PrintLog(LogType.Info, "正在等待工作线程停止...");
            while (ListenMainTask.Status == TaskStatus.Running)
            {
                System.Threading.Thread.Sleep(10);
            }
            PrintLog(LogType.Info, "侦听器停止成功！");
            return true;
        }

        /// <summary>
        /// 添加链接至侦听器中
        /// </summary>
        /// <param name="connect">要添加的链接</param>
        /// <param name="IsCheckNow">是否立即执行一次检查</param>
        /// <returns></returns>
        public virtual bool AddConnect(object connect, bool IsCheckNow = true)
        {
            lock (ListenLockObj)
            {
                lock (ListenQueue)
                {
                    ListenItem c = new ListenItem(connect);
                    if (IsCheckNow)
                    {
                        int l = CheckDataAvilable(connect);
                        if (l > 0)
                        {
                            PackConnect(c, l);
                            return true;
                        }
                    }
                    PrintLog(LogType.Info, "正在加入链接...");

                    foreach (ListenItem ci in ListenQueue.ToArray())
                    {
                        if (ci.Connect == connect)
                        {
                            PrintLog(LogType.Waring, "连接已存在，取消加入！");
                            return false;
                        }
                    }
                    ListenQueue.Add(c);
                    PrintLog(LogType.Info, "连接加入完毕！");
                    return true;
                }
            }
        }
        /// <summary>
        /// 从侦听器中移除链接
        /// </summary>
        /// <param name="connect">要移除的链接</param>
        /// <returns></returns>
        public virtual bool RemoveConnect(object connect)
        {
            lock (ListenLockObj)
            {
                lock (ListenQueue)
                {
                    PrintLog(LogType.Info, "正在移除连接...");
                    foreach (ListenItem ci in ListenQueue.ToArray())
                    {
                        if (ci.Connect == connect)
                        {
                            ListenQueue.Remove(ci);
                            PrintLog(LogType.Info, "连接移除完毕！");
                            return true;
                        }
                    }
                    PrintLog(LogType.Waring, "未找到要移除的连接，已取消操作！");
                    return true;
                }
            }
        }

        /// <summary>
        /// 清空监控列表
        /// </summary>
        public virtual void Clear()
        {
            lock (ListenLockObj)
            {
                lock (ListenQueue)
                {
                    ListenQueue.Clear();
                }
            }
            ListenQueue.Clear();
        }

        /// <summary>
        /// 获取侦听器中的链接数目
        /// </summary>
        /// <returns></returns>
        public int GetConnectCount()
        {
            return ListenQueue.Count;
        }

        /// <summary>
        /// 获取指定连接的侦听信息
        /// </summary>
        /// <param name="con"></param>
        /// <returns></returns>
        public ListenItem GetInfo(object con)
        {
            foreach (ListenItem li in ListenQueue)
            {
                if (li.Connect == con)
                {
                    return li;
                }
            }
            return null;
        }

        #endregion

    }
}
